package com.hulk.idempotent;


import com.hulk.idempotent.annotation.EnableIdempotentConfig;
import com.hulk.idempotent.strategy.IdempotentStrategy;
import com.hulk.idempotent.strategy.RedisIdempotentStrategy;
import com.hulk.idempotent.strategy.SimpleIdempotentStrategy;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 *  configuration
 * @author huanghongfei
 */
@Configuration
@ConditionalOnBean(annotation = EnableIdempotentConfig.class)
@EnableConfigurationProperties(IdempotentProperties.class)
public class IdempotentAutoConfiguration {

    @ConditionalOnClass(RedisTemplate.class)
    @Configuration
    protected static class RedisConfig{

        private IdempotentProperties properties;

        private RedisConnectionFactory redisConnectionFactory;

        public RedisConfig(RedisConnectionFactory redisConnectionFactory,IdempotentProperties properties){
            this.properties=properties;
            this.redisConnectionFactory=redisConnectionFactory;
        }

        @Bean
        public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
            RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
            redisTemplate.setKeySerializer(new StringRedisSerializer());
            redisTemplate.setHashKeySerializer(new StringRedisSerializer());
            redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer());
            redisTemplate.setHashValueSerializer(new JdkSerializationRedisSerializer());
            redisTemplate.setConnectionFactory(redisConnectionFactory);
            return redisTemplate;
        }

        @Bean
        public IdempotentStrategy redisIdempotentStrategy(){
            RedisTemplate redisTemplate=this.redisTemplate(redisConnectionFactory);
            RedisIdempotentStrategy redisIdempotentStrategy = new RedisIdempotentStrategy(redisTemplate);
            redisIdempotentStrategy.setModule(properties.getModule());
            redisIdempotentStrategy.setTimeout(properties.getTimeout());
            return redisIdempotentStrategy;
        }
    }

    @Bean
    @ConditionalOnMissingBean(IdempotentStrategy.class)
    public IdempotentStrategy simpleIdempotentStrategy(){
        IdempotentStrategy idempotentStrategy=new SimpleIdempotentStrategy();
        return idempotentStrategy;
    }

    @Bean
    public IdempotentInterceptor idempotentInterceptor (IdempotentStrategy idempotentStrategy){
        IdempotentInterceptor interceptor = new IdempotentInterceptor(idempotentStrategy);
        return interceptor;
    }


}
